昨天我們提到了 .env 的四大規則,今天我們來看看這些規則可以如何被解析吧 !
我們先研究一下, .env 的規則要如何用 code 來對應分析呢 ?
= 作為分隔符號 , 前面當變數 , 後面當值const lineStr = 'SECRET_KEY=YOURSECRETKEYGOESHERE';
const key = lineStr.substring(0, lineStr.indexOf('='));
const value = lineStr.substring(lineStr.indexOf('=') + 1);
# 後面是註解// 前面的 value 只能取到 # 前面文字
const value = lineStr.substring(lineStr.indexOf('=') + 1, lineStr.indexOf('#')).trim();
// 開頭是 # 的行 , 直接跳過
if (lineStr.trim().startsWith('#')) {
    continue;
}
" 是一對的 , 中間遇到的換行 ( \n ) . 特殊字元 ( # . = ) 不起效果// 多行模式中 ~~~
if (IS_IN_QUOTATION) {
    // 遇過結尾符的 " , 將 value 文字收納起來
    if (lineStr.indexOf('"') > -1) {
        // 取得 value 文字
        const value = tempValue + lineStr.substring(0, lineStr.indexOf('"'));
        output[tempKey] = value;
        IS_IN_QUOTATION = false;
    
    } else tempValue += lineStr + '\n';
    
    continue;
}
// 多行模式未啟動 ~~~
if (!IS_IN_QUOTATION && lineStr.indexOf('"') > -1) {
    // 單行
    if (lineStr.match(/"/g).length > 1) {
        const key = lineStr.substring(0, lineStr.indexOf('='));
        const value = lineStr.substring(lineStr.indexOf('"') + 1, lineStr.lastIndexOf('"'));
        output[key] = value;
    }
    // 多行
    else {
        IS_IN_QUOTATION = true; // 啟動多行模式
        // 先將 " 後面的文字收集起來
        tempKey = lineStr.substring(0, lineStr.indexOf('='));
        tempValue = lineStr.substring(lineStr.indexOf('"') + 1) + '\n';
    }
}
// myDotEnvParser.js
// 第一步 - 讀取檔案內容 , 取得要 Parser 的字串
const fs = require('fs');
const str = fs.readFileSync('./.env-sample', 'utf8');
// 第二步 - 定義特定字元
const EQUAL = '=';
const COMMENT = '#';
const QUOTATION = '"';
// 第三步 - 逐行讀取 , 遇到特定字元( # . " . = )做特別處理
const lineList = str.split('\n');
for (let lineno = 0; lineno < lineList.length; lineno++) {
    const lineStr = lineList[lineno];
    if (IS_IN_QUOTATION) {
        // 遇過結尾符的 " , 將 value 文字收納起來
        if (lineStr.indexOf('"') > -1) {
            // 取得 value 文字
            const value = tempValue + lineStr.substring(0, lineStr.indexOf('"'));
            output[tempKey] = value;
            IS_IN_QUOTATION = false;
        } else tempValue += lineStr + '\n';
        continue;
    }
    // # 開頭 , 整行跳過
    if (lineStr.trim().startsWith('#')) {
        continue;
    }
    // 有 " 先記錄位置
    if (lineStr.indexOf('"') > -1) {
        // 單行
        if (lineStr.match(/"/g).length > 1) {
            const key = lineStr.substring(0, lineStr.indexOf('='));
            const value = lineStr.substring(lineStr.indexOf('"') + 1, lineStr.lastIndexOf('"'));
            output[key] = value;
        }
        // 多行
        else {
            IS_IN_QUOTATION = true;
            // 先將 " 後面的文字收集起來
            tempKey = lineStr.substring(0, lineStr.indexOf('='));
            tempValue = lineStr.substring(lineStr.indexOf('"') + 1) + '\n';
        }
    }
    // 有 = 取變數名稱跟值
    if (lineStr.indexOf('=') > -1 && lineStr.indexOf('"') === -1) {
        const key = lineStr.substring(0, lineStr.indexOf('='));
        const value = lineStr.substring(lineStr.indexOf('=') + 1, lineStr.indexOf('#')).trim();
        output[key] = value;
    }
}
console.log('output=', output);